﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SimTank
{
    public partial class BaseMob
    {
        virtual protected int Block(int damage)
        {
            return (int)(damage * (1 - 0.3));
        }

        virtual protected int ApplyDR(int damage, BaseMob Attacker)
        {
            double armorreduction;
            if (Attacker.level <= 80)
                armorreduction = armor / (armor + Attacker.level * 467.5 - 22167.5);
            else
                armorreduction = armor / (armor + Attacker.level * 2167.5 - 158167.5);
            return (int)(damage * armorreduction);
        }

        virtual public void Incoming(List<Attack> incomingattacks, BaseMob Attacker)
        {
            if (Attacker.unitid == target)
            {
                TargetDebuffList = Attacker.DebuffList;
            }

            foreach (Attack incoming in incomingattacks)
            {
                if (incoming != null)
                {
                    int combat_roll = random.Next(10000);

                    double effective_dodge = dodge;
                    double effective_parry = parry;
                    double effective_miss = miss;
                    double effective_block = block;
                    double effective_crit = crit;

                    if (effective_dodge < 0) { effective_dodge = 0; }
                    if (effective_parry < 0) { effective_parry = 0; }

                    int outcome = 0;

                    /*
                     * Combat Table
                     * 1 = miss
                     * 2 = parry
                     * 3 = dodge
                     * 4 = block
                     * 5 = critical
                     * 6 = hit
                     * 7 = dot tick
                     */

                    if (incoming.isAvoidable)
                    {
                        if (combat_roll < miss)
                        {
                            misses++;
                            outcome = 1;
                        }
                        else if (combat_roll < miss + parry)
                        {
                            parries++;
                            outcome = 2;
                        }
                        else if (combat_roll < dodge + parry + miss)
                        {
                            dodges++;
                            outcome = 3;
                        }
                        else if (combat_roll < dodge + parry + miss + block)
                        {
                            blocks++;
                            outcome = 4;
                        }
                        else if (combat_roll < crit + dodge + parry + miss + block)
                        {
                            hits++;
                            outcome = 5;
                        }
                        else
                        {
                            hits++;
                            outcome = 6;
                        }
                    }
                    else //its unavoidable, can only miss or crit or hit
                    {
                        if (combat_roll < miss)
                        {
                            misses++;
                            outcome = 1;
                        }
                        else if (combat_roll < crit + miss)
                        {
                            hits++;
                            outcome = 5;
                        }
                        else
                        {
                            hits++;
                            outcome = 6;
                        }
                    }

                    int reduced_damage = 0;
                    if (outcome == 4 && incoming.spellschool == SchoolEnum.Physical)  //physical attacks can be blocked and are affected by armor
                        reduced_damage = Block(ApplyDR(incoming.damage, Attacker));
                    else if (outcome >= 5 && incoming.spellschool == SchoolEnum.Physical) //hit or crits physical attacks are only affected by armor
                        reduced_damage = ApplyDR(incoming.damage, Attacker);
                    else if (outcome >= 5) //if it wasn't one of the above, its not affected by armor (go figure)
                        reduced_damage = incoming.damage;

                    if (outcome == 5)
                    {
                        reduced_damage = (int)(reduced_damage * incoming.critmodifier);
                    }

                    Attacker.ReturnResult(incoming.spellID, outcome);
                        

                    if (trackttl)
                        observedTimeToLive(reduced_damage);

                    damagetaken += reduced_damage;
                }
            }
        }

        virtual public TargettedAttack Action()
        {
            TargettedAttack ret = new TargettedAttack();
            swingremaining--;
            if (swingremaining <= 0)
            {
                int hit_size = random.Next(damage_min, damage_max);
                swingremaining = swinglength;
                attacks++;
                Attack melee = new Attack("Melee", hit_size, SchoolEnum.Physical);
                ret.attack.Add(melee);
            }
            ret.targetuid = target;
            ret.sourceuid = unitid;
            return ret;
        }
        
        virtual public void UseCooldowns()
        {
            
        }

        virtual public void ReturnResult(int SpellID, int result)
        {
        }

        protected bool CheckSpellConditionals(attackQueueObject conditions)
        {
            if (CheckResourceMax(conditions.resourceMax) &&
                CheckResourceMin(conditions.resourceMin) &&
                CheckBuffPresent(conditions.buffPresentSpellID, conditions.buffPresentStack) &&
                CheckDebuffPresent(conditions.debuffPresentSpellID, conditions.debuffStack))
            {
                return true;
            }
            else
                return false;
        }

        protected virtual bool CheckResourceMax(int resourceMax)
        {
            return true;
        }

        protected virtual bool CheckResourceMin(int resourceMin)
        {
            return true;
        }

        protected bool CheckBuffPresent(int SpellID, int DesiredStackSize)
        {
            if (SpellID == 0)
            {
                return true;
            }
            int buffindex = BuffList.FindIndex(delegate(Buff b) { return b.Id == SpellID; });
            if (buffindex != -1 && BuffList[buffindex].stack >= DesiredStackSize)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        protected bool CheckDebuffPresent(int SpellID, int DesiredStackSize)
        {
            if (SpellID == 0)
            {
                return true;
            }
            int debuffindex = TargetDebuffList.FindIndex(delegate(Debuff d) { return d.SpellID == SpellID; });
            if (debuffindex != -1 && TargetDebuffList[debuffindex].currentstack < DesiredStackSize)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}